using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

using ComponentFactory.Krypton.Toolkit;

using Microsoft.Build.Evaluation;

using SceneEngine;

namespace SceneEditor
{
    public partial class SceneForm : ComponentFactory.Krypton.Toolkit.KryptonForm
    {
        private string contentPath;
        private List<string> sceneNames;

        public string ScenePath
        {
            get { return (lbScenes.SelectedItem as KryptonListItem).Tag as string; }
        }

        public SceneForm(string contentPath)
        {
            this.contentPath = contentPath;

            InitializeComponent();
            SetUpScenes();
        }

        private void SetUpScenes()
        {
            Stack<string> stack = new Stack<string>();
            List<string> sceneFiles = new List<string>();

            sceneNames = new List<string>();
            lbScenes.Items.Clear();

            stack.Push(Path.GetDirectoryName(contentPath));

            while (stack.Count > 0)
            {
                string dir = stack.Pop();

                List<string> files = new List<string>();
                files.AddRange(Directory.GetFiles(dir, "*.scn"));

                foreach (string dn in Directory.GetDirectories(dir))
                    stack.Push(dn);

                foreach (string fileName in files)
                {
                    string sceneName = Path.GetFileNameWithoutExtension(fileName);

                    KryptonListItem sceneItem = new KryptonListItem(sceneName);
                    sceneItem.Tag = fileName;

                    lbScenes.Items.Add(sceneItem);
                    sceneNames.Add(sceneName);
                }
            }
        }

        private void btnAddScene_Click(object sender, EventArgs e)
        {
            TextEntryForm textForm = new TextEntryForm();
            textForm.Text = "Choose a name for your scene";
            textForm.lblText.Text = "Name";

            bool suitableNameChosen = false;

            while (!suitableNameChosen)
            {
                DialogResult textResult = textForm.ShowDialog();

                if (textResult != DialogResult.OK)
                    return;

                if (sceneNames.Contains(textForm.tbText.Text))
                    MessageBox.Show("A scene with that name already exists. Please choose a different name");
                else
                    suitableNameChosen = true;
            }

            string directory = Path.Combine(contentPath, "Scenes");

            if (!Directory.Exists(directory))
                Directory.CreateDirectory(directory);

            string scenePath = Path.Combine(directory, textForm.tbText.Text + ".scn");

            if (File.Exists(scenePath))
            {
                DialogResult messageResult = MessageBox.Show("A scene at this location already exists, do you want to ovewrite it?",
                    "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);

                if (messageResult != DialogResult.Yes)
                    return;
            }

            Scene scene = new Scene();
            scene.Save(scenePath);

            AddSceneToContentProject(scenePath, EditorGlobals.ContentProjectPath);

            KryptonListItem sceneItem = new KryptonListItem(textForm.tbText.Text);
            sceneItem.Tag = scenePath;

            lbScenes.Items.Add(sceneItem);
        }
        private void btnRemoveScene_Click(object sender, EventArgs e)
        {
            if (lbScenes.SelectedIndex < 0)
            {
                MessageBox.Show("Please select a scene from the list of scenes", "Selection Error", MessageBoxButtons.OK, MessageBoxIcon.None);
                return;
            }

            string scenePath = (lbScenes.SelectedItem as KryptonListItem).Tag as string;

            if (File.Exists(scenePath))
            {
                DialogResult messageResult = MessageBox.Show(string.Format("Are you sure you would like to delete {0}?", Path.GetFileName(scenePath)),
                    "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);

                if (messageResult != DialogResult.Yes)
                    return;
            }


            sceneNames.Remove((lbScenes.SelectedItem as KryptonListItem).ShortText);

            File.Delete(scenePath);
            RemoveSceneFromContentProject(scenePath, EditorGlobals.ContentProjectPath);

            lbScenes.Items.RemoveAt(lbScenes.SelectedIndex);

            if (lbScenes.Items.Count > 0)
                lbScenes.SelectedIndex = 0;
            else
                lbScenes.SelectedIndex = -1;
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;
            this.Close();
        }
        private void btnRefreshScene_Click(object sender, EventArgs e)
        {
            SetUpScenes();
        }

        public void AddSceneToContentProject(string filePath, string contentPath)
        {
            Project contentProject = EditorGlobals.GetProject(contentPath);

            string name = Path.GetFileNameWithoutExtension(filePath);
            string link = Path.GetFileName(filePath);
            string directoryName = Path.GetFileName(Path.GetDirectoryName(filePath));
            string path = "Scenes";
            path = Path.Combine(path, link);

            ProjectItem newItem = contentProject.AddItem("Compile", path)[0];
            newItem.SetMetadataValue("Name", name);
            newItem.SetMetadataValue("Importer", "EngineXmlImporter");
            newItem.SetMetadataValue("Processor", "EngineSceneProcessor");

            contentProject.Save();
        }
        public void RemoveSceneFromContentProject(string filePath, string contentPath)
        {
            Project contentProject = EditorGlobals.GetProject(contentPath);

            string directory = Path.GetFileName(Path.GetDirectoryName(filePath));
            string relativePath = Path.Combine(directory, Path.GetFileName(filePath));

            foreach (ProjectItem projectItem in contentProject.GetItems("Compile"))
            {
                if (projectItem.EvaluatedInclude == relativePath)
                {
                    contentProject.RemoveItem(projectItem);
                    break;
                }
            }

            contentProject.Save();
        }
    }
}